/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.core.data.extendhandler;

import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.entity.accessor.base.IAccessor;
import com.inspur.edp.cef.entity.accessor.base.ReadonlyDataException;
import com.inspur.edp.cef.entity.accessor.entity.AccessorCollection;
import com.inspur.edp.cef.entity.accessor.entity.IEntityAccessor;
import com.inspur.edp.cef.entity.changeset.AddChangeDetail;
import com.inspur.edp.cef.entity.changeset.DeleteChangeDetail;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IEntityDataCollection;
import com.inspur.edp.cef.spi.extend.datatype.ICefDataExtend;
import com.inspur.edp.cef.spi.extend.entity.ICefAddedChildDataExtend;
import com.inspur.edp.cef.spi.extend.entity.ICefEntityDataExtend;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.var;

public class EntityAccExtHandler extends AccBaseExtHandler {

   private Map<String, IEntityDataCollection> extendChildDataCollection = new HashMap<>();

   public EntityAccExtHandler(IEntityAccessor belong, boolean r) {
      super(belong, r);
   }

   @Override
   protected IEntityAccessor getBelong() {
      return (IEntityAccessor) super.getBelong();
   }

   @Override
   protected void onAddingExtend(ICefDataExtend ext, ICefData extendData) {
      super.onAddingExtend(ext, extendData);
      ICefEntityDataExtend dataExt =
          ext instanceof ICefEntityDataExtend ? (ICefEntityDataExtend) ext : null;
      if (dataExt == null) {
         return;
      }
      List<ICefAddedChildDataExtend> addedChilds = dataExt.getAddedChilds();
      if (addedChilds != null && !addedChilds.isEmpty()) {
         for (ICefAddedChildDataExtend childExt : addedChilds) {
            AccessorCollection childCollection =
                (AccessorCollection) (getIsReadonly() ? childExt
                    .createReadonlyAccessorCollection(getBelong())
                    : childExt.createAccessorCollection(getBelong()));
            childCollection.setParent(getBelong());
            extendChildDataCollection.put(childExt.getCode(), childCollection);
         }
      }
   }

   @Override
   public void clear() {
      super.clear();
      extendChildDataCollection.clear();
   }

   @Override
   public void acceptChange(IChangeDetail change) {
      super.acceptChange(change);
//      //子表
//      if (!(change instanceof ModifyChangeDetail)) {
//         return;
//      }
//      var childsChange = ((ModifyChangeDetail) change).getChildChanges();
//      if (childsChange == null || childsChange.isEmpty()) {
//         return;
//      }
//      for (Map.Entry<String, Map<String, IChangeDetail>> childChanges : childsChange.entrySet()) {
//         if (childChanges.getValue() == null || childChanges.getValue().isEmpty()) {
//            continue;
//         }
//         var currentChildCollection = extendChildDataCollection.get(childChanges.getKey());
//         if (currentChildCollection == null) {
//            continue;
//         }
//         for (Map.Entry<String, IChangeDetail> childChange : childChanges.getValue().entrySet()) {
//            Objects.requireNonNull(childChange.getValue());
//            if (childChange.getValue() instanceof DeleteChangeDetail) {
//               currentChildCollection.remove(childChange.getKey());
//            } else if (childChange.getValue() instanceof AddChangeDetail) {
//               currentChildCollection
//                   .add(((AddChangeDetail) childChange.getValue()).getEntityData());
//            } else if (childChange.getValue() instanceof ModifyChangeDetail) {
//
//            } else {
//               throw new RuntimeException(
//                   "unknown change for extended child: " + childChange.getClass());
//            }
//         }
//      }
   }

   public Map<String, IEntityDataCollection> getChilds() {
      return extendChildDataCollection;
   }

   public boolean createChild(String childCode, RefObject<ICefData> result) {
      if (getIsReadonly()) {
         throw new ReadonlyDataException();
      }
      if (getExtendList() != null) {
         for (var extend : getExtendList()) {
            ICefEntityDataExtend dataExt =
                extend instanceof ICefEntityDataExtend ? (ICefEntityDataExtend) extend : null;
            if (dataExt == null) {
               continue;
            }
            List<ICefAddedChildDataExtend> addedChilds = dataExt.getAddedChilds();
            if (addedChilds == null || addedChilds.isEmpty()) {
               continue;
            }
            for (ICefAddedChildDataExtend childExt : addedChilds) {
               if (!childExt.getCode().equals(childCode)) {
                  continue;
               }
               result.argvalue = childExt.createAccessor(
                   ((IEntityData) getBelong().getInnerData()).createChild(childCode));
               return true;
            }
         }
      }
      result.argvalue = null;
      return false;
   }

   public boolean getExtendedChild(String nodeCode, RefObject<IEntityDataCollection> result) {
      result.argvalue = extendChildDataCollection.get(nodeCode);
      return result.argvalue != null;
   }

   public boolean createAndSetChildCollection(String childCode,
       RefObject<IEntityDataCollection> result) {
      if (getExtendList() != null) {
         for (var extend : getExtendList()) {
            ICefEntityDataExtend dataExt =
                extend instanceof ICefEntityDataExtend ? (ICefEntityDataExtend) extend : null;
            if (dataExt == null) {
               continue;
            }
            List<ICefAddedChildDataExtend> addedChilds = dataExt.getAddedChilds();
            if (addedChilds == null || addedChilds.isEmpty()) {
               continue;
            }
            for (ICefAddedChildDataExtend childExt : addedChilds) {
               if (!childExt.getCode().equals(childCode)) {
                  continue;
               }
               AccessorCollection childCollection =
                   (AccessorCollection) (getIsReadonly() ? childExt
                       .createReadonlyAccessorCollection(null)
                       : childExt.createAccessorCollection(null));
               childCollection.setParent(getBelong());
               extendChildDataCollection.put(childExt.getCode(), childCollection);
               result.argvalue = childCollection;
               return true;
            }
         }
      }
      result.argvalue = null;
      return false;
   }

   @Override
   protected Object clone() throws CloneNotSupportedException {
      EntityAccExtHandler rez = (EntityAccExtHandler) super.clone();
      rez.extendChildDataCollection = new HashMap<>();
      return rez;
   }

   @Override
   public AccBaseExtHandler copy(IAccessor belong) {
      EntityAccExtHandler rez = null;
      try {
         rez = (EntityAccExtHandler) super.copy(belong);
      } catch (CloneNotSupportedException e) {
         throw new RuntimeException(e);
      }
      //子表
//      rez.extendChildDataCollection.entrySet().forEach(item -> {
//         ((AccessorCollection) item.getValue()).setParent((IEntityAccessor) belong);
//         var currentChild = extendChildDataCollection.get(item.getKey());
//         if (currentChild != null && !currentChild.isEmpty()) {
//            currentChild.forEach(child -> item.getValue().add((IEntityData) child.copy()));
//         }
//      });
      for (Map.Entry<String, IEntityDataCollection> item : extendChildDataCollection.entrySet()) {
         rez.extendChildDataCollection.put(item.getKey(),
             ((AccessorCollection) item.getValue()).copy((IEntityAccessor) belong));
      };
      return rez;
   }
}
